package es.deusto.pfc.garuda.server.net;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.PortUnreachableException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.channels.IllegalBlockingModeException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import es.deusto.pfc.garuda.server.ClientManager;

public class Net extends Thread
{
	public static int MTU;
	private static Net instance;
	private ClientManager clientManager;
	private ExecutorService threadPool = Executors.newCachedThreadPool();
	private DatagramSocket listeningSocket;
	private boolean stop;

	private Net(ClientManager clientManager)
	{
		super();
		if (clientManager != null)
			try
			{
				this.clientManager = clientManager;
				NetworkInterface networkInterface = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
				System.out.println(networkInterface);
				MTU = networkInterface.getMTU();
				listeningSocket = new DatagramSocket(31173);
			}
			catch (NullPointerException e)
			{
				e.printStackTrace();
			}
			catch (SocketException e)
			{
				e.printStackTrace();
			}
			catch (UnknownHostException e)
			{
				e.printStackTrace();
			}
	}
	
	public static Net getInstance(ClientManager clientManager)
	{
		if (instance == null)
			instance = new Net(clientManager);
		return instance;
	}

	@Override
	public void run()
	{
		DatagramPacket packet;
		
		stop = false;
		
		try
		{
			while (!stop)
			{
				packet = new DatagramPacket(new byte[MTU], MTU);
				listeningSocket.receive(packet);
				System.out.println(packet.getSocketAddress());
				threadPool.execute(new NetWorkerThread(listeningSocket, clientManager, packet));
			}
		}
		catch (SocketTimeoutException e)
		{
			e.printStackTrace();
		}
		catch (PortUnreachableException e)
		{
			e.printStackTrace();
		}
		catch (IllegalBlockingModeException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
	
	public void gracefullyStop()
	{
		stop = true;
		threadPool.shutdown();
		while (!threadPool.isTerminated());
	}
}
